package util;

import java_cup.runtime.*;
import util.sym;

%%

%class CLexer
%column
%line
%cup

%{
	   public static String currentLine;
	   
	   private Symbol symbol(int type) {
	       currentLine = "line " + yyline;
		   return new Symbol(type, yyline, yycolumn);
   	   }
   	
 	   private Symbol symbol(int type, Object val) {
           currentLine = "line " + yyline;
		   return new Symbol(type, yyline, yycolumn, val);
   	   }
   	   
   	   public String current_lexeme(){
            int l = yyline+1;
            int c = yycolumn+1;
            return "line: " + l + ", column: " + c + ", with : '"+yytext()+"')";
      }
%}

/* Macros */

D = [0-9]
L = [a-zA-Z_]
H = [a-fA-F0-9]
E = [Ee][+-]?{D}+
FS = (f|F|l|L)
IS = (u|U|l|L)*
Comment = "/*" [^*] ~"*/" | "/*" "*"+ "/"

%%

/* Definicoes */

"auto"          { return symbol(sym.AUTO, new String(yytext())); }
"break"         { return symbol(sym.BREAK, new String(yytext())); }
"case"          { return symbol(sym.CASE, new String(yytext())); }
"char"          { return symbol(sym.CHAR, new String(yytext())); }
"const"         { return symbol(sym.CONST, new String(yytext())); }
"continue"      { return symbol(sym.CONTINUE, new String(yytext())); }
"default"       { return symbol(sym.DEFAULT, new String(yytext())); }
"do"            { return symbol(sym.DO, new String(yytext())); }
"double"        { return symbol(sym.DOUBLE, new String(yytext())); }
"else"          { return symbol(sym.ELSE, new String(yytext())); }
"enum"          { return symbol(sym.ENUM, new String(yytext())); }
"extern"        { return symbol(sym.EXTERN, new String(yytext())); }
"float"         { return symbol(sym.FLOAT, new String(yytext())); }
"for"           { return symbol(sym.FOR, new String(yytext())); }
"goto"          { return symbol(sym.GOTO, new String(yytext())); }
"if"            { return symbol(sym.IF, new String(yytext())); }
"int"           { return symbol(sym.INT, new String(yytext())); }
"long"          { return symbol(sym.LONG, new String(yytext())); }
"register"      { return symbol(sym.REGISTER, new String(yytext())); }
"return"        { return symbol(sym.RETURN, new String(yytext())); }
"short"         { return symbol(sym.SHORT, new String(yytext())); }
"signed"        { return symbol(sym.SIGNED, new String(yytext())); }
"sizeof"        { return symbol(sym.SIZEOF, new String(yytext())); }
"static"        { return symbol(sym.STATIC, new String(yytext())); }
"struct"        { return symbol(sym.STRUCT, new String(yytext())); }
"switch"        { return symbol(sym.SWITCH, new String(yytext())); }
"typedef"       { return symbol(sym.TYPEDEF, new String(yytext())); }
"union"         { return symbol(sym.UNION, new String(yytext())); }
"unsigned"      { return symbol(sym.UNSIGNED, new String(yytext())); }
"void"          { return symbol(sym.VOID, new String(yytext())); }
"volatile"      { return symbol(sym.VOLATILE, new String(yytext())); }
"while"         { return symbol(sym.WHILE, new String(yytext())); }

0[xX]{H}+{IS}?      { return symbol(sym.CONSTANT, new String(yytext())); }
0{D}+{IS}?      { return symbol(sym.CONSTANT, new String(yytext())); }
{D}+{IS}?       { return symbol(sym.INTEGER, new String(yytext())); }
L?'(\\.|[^\\'])+'   { return symbol(sym.CHAR, new String(yytext())); }

{D}+{E}{FS}?        { return symbol(sym.CONSTANT, new String(yytext())); }
{D}*"."{D}+({E})?{FS}?  { return symbol(sym.CONSTANT, new String(yytext())); }
{D}+"."{D}*({E})?{FS}?  { return symbol(sym.CONSTANT, new String(yytext())); }

"..."           { return symbol(sym.ELLIPSIS, new String(yytext())); }
">>="           { return symbol(sym.RIGHT_ASSIGN, new String(yytext())); }
"<<="           { return symbol(sym.LEFT_ASSIGN, new String(yytext())); }
"+="            { return symbol(sym.ADD_ASSIGN, new String(yytext())); }
"-="            { return symbol(sym.SUB_ASSIGN, new String(yytext())); }
"*="            { return symbol(sym.MUL_ASSIGN, new String(yytext())); }
"/="            { return symbol(sym.DIV_ASSIGN, new String(yytext())); }
"%="            { return symbol(sym.MOD_ASSIGN, new String(yytext())); }
"&="            { return symbol(sym.AND_ASSIGN, new String(yytext())); }
"^="            { return symbol(sym.XOR_ASSIGN, new String(yytext())); }
"|="            { return symbol(sym.OR_ASSIGN, new String(yytext())); }
">>"            { return symbol(sym.RIGHT_OP, new String(yytext())); }
"<<"            { return symbol(sym.LEFT_OP, new String(yytext())); }
"++"            { return symbol(sym.INC_OP, new String(yytext())); }
"--"            { return symbol(sym.DEC_OP, new String(yytext())); }
"->"            { return symbol(sym.PTR_OP, new String(yytext())); }
"&&"            { return symbol(sym.AND_OP, new String(yytext())); }
"||"            { return symbol(sym.OR_OP, new String(yytext())); }
"<="            { return symbol(sym.LE_OP, new String(yytext())); }
">="            { return symbol(sym.GE_OP, new String(yytext())); }
"=="            { return symbol(sym.EQ_OP, new String(yytext())); }
"!="            { return symbol(sym.NE_OP, new String(yytext())); }
";"         { return symbol(sym.SEMI_COLON, new String(yytext())); }
("{"|"<%")      { return symbol(sym.OPEN_BRACE, new String(yytext())); }
("}"|"%>")      { return symbol(sym.CLOSE_BRACE, new String(yytext())); }
","         { return symbol(sym.COMMA, new String(yytext())); }
":"         { return symbol(sym.COLON, new String(yytext())); }
"="         { return symbol(sym.EQUALS, new String(yytext())); }
"("         { return symbol(sym.OPEN_PARENTHESIS, new String(yytext())); }
")"         { return symbol(sym.CLOSE_PARENTHESIS, new String(yytext())); }
("["|"<:")      { return symbol(sym.OPEN_BRACKETS, new String(yytext())); }
("]"|":>")      { return symbol(sym.CLOSE_BRACKETS, new String(yytext())); }
"."         { return symbol(sym.DOT, new String(yytext())); }
"&"         { return symbol(sym.AMPERSAND, new String(yytext())); }
"!"         { return symbol(sym.EXCLAMATION_MARK, new String(yytext())); }
"~"         { return symbol(sym.TILDE, new String(yytext())); }
"-"         { return symbol(sym.MINUS, new String(yytext())); }
"+"         { return symbol(sym.PLUS, new String(yytext())); }
"*"         { return symbol(sym.ASTERISK, new String(yytext())); }
"/"         { return symbol(sym.SLASH, new String(yytext())); }
"%"         { return symbol(sym.PERCENT, new String(yytext())); }
"<"         { return symbol(sym.LESS_THAN, new String(yytext())); }
">"         { return symbol(sym.MORE_THAN, new String(yytext())); }
"^"         { return symbol(sym.SWUN_DASH, new String(yytext())); }
"|"         { return symbol(sym.PIPE, new String(yytext())); }
"?"         { return symbol(sym.QUESTION_MARK, new String(yytext())); }

{L}({L}|{D})*   { return symbol(sym.IDENTIFIER, new String(yytext())); }
\"([^\\\"]|\\.)*\" { return symbol(sym.STRING_LITERAL, new String(yytext())); }

{Comment}	{ }

[ \t\v\n\f] {   }
<<EOF>> { return symbol(sym.EOF); }

/* No token was found for the input so through an error.  Print out an
   Illegal character message with the illegal character that was found. */
[^]                    { throw new Error("Error recognizing: " + current_lexeme()); }